#!/bin/bash
#
#******************************************************************************
# bootstrap (XPC)
#------------------------------------------------------------------------------
##
# \file       	bootstrap
# \library    	XPC
# \author     	Chris Ahlstrom
# \date       	2008-03-02
# \update     	2012-03-04
# \version    	$Revision$
# \license    	$XPC_SUITE_GPL_LICENSE$
#
#     The above is modified by the following to remove even the mild GPL
#     restrictions:
#
#     Use this script in any manner whatsoever.  You
#     don't even need to give me any credit.
#
#     However, keep in mind the value of the GPL in keeping software and its
#     descendant modifications available to the community for all time.
#
#------------------------------------------------------------------------------

source scripts/bfunctions

if [ $? != 0 ] ; then
   echo "'source scripts/bfunctions' failed.  Must abort."
   exit 255
fi

#------------------------------------------------------------------------------
#
# Autoconf bootstrap script for the XPC library suite:
#
#     Bash, not sh, is required; some systems do not symlink sh to bash.
#
#     This file creates the proper environment for development.  It also
#     runs the configure script by default.
#
#     Run "./bootstrap --help" for options.
#
#     Run "./bootstrap --make" to rebuild the configuration, make the
#     libraries and executables, make the documentation, and make the tags
#     files for emacs and vi editing.
#
#     This file is the Bootstrap file for the automake setup of the XPC
#     directory.  The following subnotes apply.
#
# aclocal -I config:
#
#     Generates aclocal.m4 (by scanning configure.ac).  The following option
#     applies:
#
#        -I config      Adds directory "config" to the search list for m4 files.
#
# libtoolize --force --copy:
#
#     Allows the building of the project using libtool.  --force causes the
#     libtools files to always be overwritten. --copy means copy the libtool
#     files instead of symlinking to them.
#
# autoheader:
#
#     Generates configuration headers.
#
# automake --foreign --add-missing --copy:
#
#        --foreign      Relaxes GNU standards for the files that
#                       should be present in a GNU distribution.
#
#        --add-missing  Creates the skeleton files that document an
#                       GNU project.
#
#        --copy         Copy the skeleton files, rather than making a
#                       symlink.
#
# autoconf:
#
#     This call reads configure.in and uses it to create the rest of the stuff
#     needed to build the project.
#
# gettextize (now known as 'autopoint'):
#
#     This call prepares the project for the usage of gettext features.
#     It is not completely used in the XPC project (at this time), but is
#     supported.
#
#     Also note that autopoint requires CVS to be installed.
#
#     Also need automake-1.8 or above to guarantee some new macros.
#
# gcc versions:
#
#     Very old compilers (e.g. gcc 2.95.4) are not supported by this project.
#     You will want to upgrade your compiler.
#
# Purpose:
#
#     This script is meant to be used by a developer to setup this project
#     from scratch, and generated and run a GNU automake configure script.
#
#     Run the command "./bootstrap --help" for more information.
#
#------------------------------------------------------------------------------

DOBACKUP="no"
DOCONFIGURE="no"
DOBOOTSTRAP="yes"
DOINTLBOOT="no"
DODEBUG="no"
DOCLEAN="no"
DOSUPERCLEAN="no"
DODEBCLEAN="no"
DOLOG="no"
LOGFILENAME=""
OLDCONF="no"
M4DIR="m4"

#******************************************************************************
# Help
#------------------------------------------------------------------------------

if [ "$1" == "--help" ] ; then

   cat << E_O_F

XPC Library Suite bootstrap $XPC_LIBRARY_VERSION $XPC_SCRIPT_EDIT_DATE

Usage: $0 [options]

   The XPC library suite provides some useful C/C++ libraries and test
   applications.  This script sets up the GNU automake support for this
   project.  It can also run the 'configure' script and clean up files that
   'make clean' misses.  The following options apply:

 --intl-boot         After bootstrapping, call 'bootstrap-po --boot' to recreate
                     the po (internationalization) files from scratch.  [$DOINTLBOOT]
 --configure, -c     After bootstrapping, run the 'configure' script.  [$DOCONFIGURE]
                     Note that configuration done by 'bootstrap' is in-source; 
                     to do an out-of-source configuration, use the 'build' script
                     or change to the desired directory and run '../configure'.
                     In fact, we recommend using the 'build' script.  Run
                     './build --help' for more information.
 --no-configure,     Do not run the 'configure' script; just set up the GNU
  -nc                autotools files (bootstrap it).  Use this option and run
                     'configure' for debugging, stack-checking, etc.
 --reconstruct       After bootstrapping, also do --intl-boot, then configure
                     a standard in-source build. Used for basic build testing.
 --debug, -ed,       Does --configure with the --enable-debug flag.  Note that
 --enable-debug      creation of shared libraries is disabled for debugging.
                     Also note that 'bootstrap' does not provide the
                     --enable-coverage and --enable-profile options.
 --clean             Delete all derived and junk files from the project.  [$DOCLEAN]
                     Does not imply --deb-clean or --super-clean.
 --super-clean       Also clean out the po directory, which backs up the *.po
                     files in that directory. [$DOSUPERCLEAN]  Be careful!
 --deb-clean         Just remove the files created by running the various
                     debian/rules script options. [$DODEBCLEAN]
 --log file          Write the main commands to the given file.  [$DOLOG] This
                     is a good check of the progress of the bootstrap script.

The default is to bootstrap the project.  The developer should then run
'configure', which sets it up for a normal release build.  Another common
option is --enable-debug, which also adds the --disable-shared flag to the
configure operation.

Also note that you have to run the 'bootstrap-po' script for setting up
internationalization.  Run './bootstrap-po --help' for more information.

Better still, run the 'build' script to do the work for you.  Run
'./build --help' for more information.

E_O_F

   exit 1
fi

if [ $# -ge 1 ] ; then

   while [ "$1" != "" ] ; do

      echo "   Processing command-line option $1"
      case "$1" in

         --intl-boot)
            DOINTLBOOT="yes"
            ;;

         --no-configure | -nc)
            DOCONFIGURE="no"
            ;;

         --configure | -c)
            DOCONFIGURE="yes"
            ;;

         --enable-debug | --debug | -d | -ed)
            DOCONFIGURE="yes"
            DODEBUG="yes"
            ;;

         --reconstruct)
            DOBOOTSTRAP="yes"
            DOINTLBOOT="yes"
            DOCONFIGURE="yes"
            ;;

         --clean)
            DOCLEAN="yes"
            DOBACKUP="yes"
            ;;

         --super-clean)
            DOCLEAN="yes"
            DOSUPERCLEAN="yes"
            ;;

         --deb-clean)
            DODEBCLEAN="yes"
            ;;

         --log)
            DOLOG="yes"
            shift
            LOGFILENAME="$1"
            if [ "$LOGFILENAME" == "" ] ; then
               die 5 "CLI" "Please specify a --log name."
            fi
            SUBSTR="${LOGFILENAME:0}"
            if [ $SUBSTR == "-" ] || [ $SUBSTR == "--" ] ; then
               die 5 "CLI" "Please specify a legal (no hyphen) --log name."
            fi
            ;;

         --die-test)
               die 256 "TEST" "Please specify a legal non-test option," "idiot."
            ;;

         *)
            echo "? Unsupported XPC bootstrap option; --help for more information" ;
            exit $EXIT_ERROR_NO_SUCH_OPTION
            ;;

      esac

      shift

   done

fi

if [ $DOLOG == "yes" ] ; then

   if [ "$LOGFILENAME" == "" ] ; then

      echo "? Missing name for the --log option."
      exit $EXIT_ERROR_LOG

   else

      echo "Logging main commands to $LOGFILENAME..."
      if [ ! -f $LOGFILENAME ] ; then

         touch $LOGFILENAME
         if [ $? != 0 ] ; then
            die 10 "LOG" "? Creating log-file $LOGFILENAME failed, aborting!"
         else
            log "XPC build script" "`date`"
         fi
      fi
   fi
fi

#******************************************************************************
# Script helper function
#------------------------------------------------------------------------------

cmd()
{
   if [ "$DOBOOTSTRAP" == "yes" ] ; then

      echo "Running XPC library suite build command $*"
      if [ -x /usr/bin/$1 ] ; then

         if ! $* ; then
            echo The bootstrap command failed!
            exit $EXIT_ERROR_NO_SUCH_COMMAND
         fi

      else

         echo "Program $1 does not exist, exiting script!"
         if [ "$1" == "autopoint" ] ; then

            cat << E_O_F
Install the gettext package to obtain the autopoint application.  It also
requires cvs to be installed.  (Other packages you might not have installed
yet: pkg-config.)

E_O_F

         fi
         exit $EXIT_ERROR_NO_SUCH_COMMAND
      fi
   fi
}

#******************************************************************************
# Script helper function for cleaning out auto-copied m4 files
#------------------------------------------------------------------------------

clean_m4()
{
   rm -f m4/codeset.m4
   rm -f m4/gettext.m4
   rm -f m4/glibc2.m4
   rm -f m4/glibc21.m4
   rm -f m4/iconv.m4
   rm -f m4/intdiv0.m4
   rm -f m4/intl.m4
   rm -f m4/intldir.m4
   rm -f m4/intmax.m4
   rm -f m4/inttypes-pri.m4
   rm -f m4/inttypes_h.m4
   rm -f m4/lcmessage.m4
   rm -f m4/lib-ld.m4
   rm -f m4/lib-link.m4
   rm -f m4/lib-prefix.m4
   rm -f m4/libtool.m4
   rm -f m4/lock.m4
   rm -f m4/longdouble.m4
   rm -f m4/longlong.m4
   rm -f m4/nls.m4
   rm -f m4/po.m4
   rm -f m4/printf-posix.m4
   rm -f m4/progtest.m4
   rm -f m4/size_max.m4
   rm -f m4/stdint_h.m4
   rm -f m4/uintmax_t.m4
   rm -f m4/ulonglong.m4
   rm -f m4/visibility.m4
   rm -f m4/wchar_t.m4
   rm -f m4/wint_t.m4
   rm -f m4/xsize.m4
}

#******************************************************************************
# Provide a sane environment, just in case it is needed.
#------------------------------------------------------------------------------

LANG=C
export LANG
CYGWIN=binmode
export CYGWIN

#******************************************************************************
# Implement the clean option.
#------------------------------------------------------------------------------
#
#     This goes well beyond "make clean" and "make distclean".  It cleans
#     out /everything/ that gets created by bootstrapping and building the
#     library and test application.
#
#------------------------------------------------------------------------------

if [ $DOCLEAN == "yes" ] ; then

   if [ ! -d src ] ; then
      echo "COULD NOT FIND 'src' DIRECTORY.  Run clean from root of the project."
      exit $EXIT_ERROR_NO_SRC_DIR
   fi

# ./boot_clean

# Derived directories and other junk

   find . -name autom4te.cache -exec rm -rf '{}' \;
   find . -name aux-files -exec rm -rf '{}' \;
   find . -name config -exec rm -rf '{}' \;
   find . -name .deps -exec rm -rf '{}' \;
   find . -name .libs -exec rm -rf '{}' \;
   find . -name release -exec rm -rf '{}' \;
   find . -name debug -exec rm -rf '{}' \;
   find . -name cpp -exec rm -rf '{}' \;
   find . -name html -exec rm -rf '{}' \;
   find . -name latex -exec rm -rf '{}' \;
   find . -name i18n -exec rm -rf '{}' \;

# Derived files and other junk.  Some of this could be cleaned by
# "make clean", but we want a one-stop way to clean it all.

   find . -name "*.pdf" -exec rm -f '{}' \;

   find . -name ABOUT-NLS -exec rm -f '{}' \;
   find . -name aclocal.m4 -exec rm -f '{}' \;
   find . -name configure -exec rm -f '{}' \;
   find . -name config.h -exec rm -f '{}' \;
   find . -name config.h.in -exec rm -f '{}' \;
   find . -name config.log -exec rm -f '{}' \;
   find . -name config.status -exec rm -f '{}' \;
   find . -name _configs.sed -exec rm -f '{}' \;
   find . -name libtool -exec rm -f '{}' \;
   find . -name dox-stamp -exec rm -f '{}' \;
   find . -name stamp-h1 -exec rm -f '{}' \;
   find . -name "*.log" -exec rm -f '{}' \;
   find . -name ".*swp" -exec rm -f '{}' \;
   find . -name "*.t" -exec rm -f '{}' \;
   find . -name "*.a" -exec rm -f '{}' \;
   find . -name "*.la" -exec rm -f '{}' \;
   find . -name "*.o" -exec rm -f '{}' \;
   find . -name "*.lo" -exec rm -f '{}' \;
   find . -name "core" -exec rm -f '{}' \;
   find . -name "vgcore" -exec rm -f '{}' \;
   find . -name xpc-config.h -exec rm -f '{}' \;

# Windows artifacts

     # TBD.  We will use mingw in preference to Microsoft products.

# Clean xpccut test app:

   find . -name "unit_test_test" -exec rm -f '{}' \;

# Clean xpchello test apps:

   find . -name "bad-pointers" -exec rm -f '{}' \;
   find . -name "core-dumps" -exec rm -f '{}' \;
   find . -name "hello" -exec rm -f '{}' \;
   find . -name "setjump" -exec rm -f '{}' \;
   find . -name "xpchello_test" -exec rm -f '{}' \;

   rm -r m4/*~

# Be careful with these two:

   find . -name Makefile -exec rm -f '{}' \;
   find . -name Makefile.in -exec rm -f '{}' \;

# Don't uncomment this one:

#  find . -name ".svn" -exec rm -rf '{}' \;

   if [ $DOSUPERCLEAN == "yes" ] ; then

      ./bootstrap-po --intl-clean

   fi

   echo "   All junk files removed (even if make says there's no rules for"
   echo "   'clean', and errors seem to have occurred)."

else

   if [ $DODEBCLEAN == "yes" ] ; then

      echo "   Cleaning up debian/rules-generated files..."
      rm -f  build-stamp configure-stamp
      rm -f  debian/*.log
      rm -f  debian/files
      rm -rf debian/libXPC-dev
      rm -rf debian/libXPC1
      rm -rf debian/tmp
      exit 0

   else

      #************************************************************************
      # Set up GNU Autotools
      #------------------------------------------------------------------------

      AUTOMAKE_BAD=no
      INSTALL_BAD=no
      ACVERSION=
      ACLOCAL=aclocal${ACVERSION}
      AUTOCONF=autoconf
      AUTOHEADER=autoheader
      AUTOMAKE=automake
      AUTOPOINT=autopoint
      LIBTOOLIZE=libtoolize

      # Exit if a simple command exits with a non-zero status.

      set -e

      # After expanding a simple command, display PS4 and the command with its
      # expanded arguments.  This setting makes any error messages too
      # difficult to read:
      #
      # set -x

      # Check Autoconf version and perform clean ups if all is well.

      if [ -x `which autoconf` ] ; then

         AC_VER=`autoconf --version | head -1 | sed 's/^[^0-9]*//'`
         AC_VER_MAJOR=`echo $AC_VER | cut -f1 -d'.'`
         AC_VER_MINOR=`echo $AC_VER | cut -f2 -d'.' | sed 's/[^0-9]*$//'`

         if [ "$AC_VER_MAJOR" -lt "2" ] ; then

            echo
            echo "Autoconf 2.13 or greater may be needed to build configure."
            echo "Edit the bootstrap file to ignore this test, if desired."
            echo
            exit $EXIT_ERROR_AUTOCONF_VERSION

         fi

         if [ "$AC_VER_MINOR" -lt "13" ] ; then

            echo
            echo "Autoconf 2.13 or greater may be needed to build configure."
            echo "Edit the bootstrap file to ignore this test, if desired."
            echo
            exit $EXIT_ERROR_AUTOCONF_VERSION_2

         fi

         if [ "$AC_VER_MINOR" -lt "50" ] ; then

            if [ -e configure.ac ] ; then
               if [ ! -e configure.in ] ; then
                  ln -s configure.ac configure.in
               fi
            fi
            echo "Some warnings about cross-compiling are normal."

         else

            rm -f configure.in
            if [ -x configure ] ; then

               echo The XPC configure script already exists.  Replacing it.

            fi
         fi

      else

         cat << E_O_F

The GNU autoconf application was not found.  This project requires GNU
autoconf (and automake, autopoint, and ac-autoconf-archive) in order to
bootstrap itself.

E_O_F
         exit $EXIT_ERROR_AUTOCONF_VERSION_3
      fi

      # Check for automake.

      amvers="none"
      if automake-1.8 --version >/dev/null 2>&1; then
         amvers="-1.8"

        # If we also have 1.6 (>> 1.6.1), use it instead because it is faster

         if automake-1.6 --version >/dev/null 2>&1; then
            if expr "`automake-1.6 --version | sed -e '1s/[^0-9]*//' -e q`" ">" "1.6.1" > /dev/null 2>&1; then
               amvers="-1.6"
            fi
         fi
      elif automake-1.7 --version >/dev/null 2>&1; then
         amvers="-1.7"

         # If we also have 1.6 (>> 1.6.1), use it instead because it is faster

         if automake-1.6 --version >/dev/null 2>&1; then
            if expr "`automake-1.6 --version | sed -e '1s/[^0-9]*//' -e q`" ">" "1.6.1" > /dev/null 2>&1; then
               amvers="-1.6"
            fi
         fi

      elif automake-1.6 --version >/dev/null 2>&1; then

         amvers="-1.6"
         if expr "`automake-1.6 --version | sed -e '1s/[^0-9]*//' -e q`" "<=" "1.6.1" > /dev/null 2>&1; then
            AUTOMAKE_BAD=yes
         fi

      elif automake-1.5 --version >/dev/null 2>&1; then

         INSTALL_BAD=yes
         amvers="-1.5"

      elif automake --version > /dev/null 2>&1; then

         amvers=""
         case "`automake --version | sed -e '1s/[^0-9]*//' -e q`" in
            0|0.*|1|1.[01234]|1.[01234][-.]*)
               amvers="none" ;;
            1.5|1.5.*)
               INSTALL_BAD=yes ;;
            1.6|1.6.0|1.6.1)
               AUTOMAKE_BAD=yes ;;
         esac
      fi
   fi

#******************************************************************************
# Check for the installation of the GNU gettext facility.
# Autopoint is available from 0.11.3, but we need at least 0.11.5
#------------------------------------------------------------------------------

   # Check for pkg-config

   if pkg-config --version >/dev/null 2>&1; then
      PKGCONFIG=yes
   else
      PKGCONFIG=no
   fi

   #************************************************************************
   # Create config and m4 directories.  Note that they might be empty for
   # this project.  Also create an include directory, mainly for config.h
   # stuff.
   #------------------------------------------------------------------------

   mkdir -p aux-files
   mkdir -p config
   mkdir -p m4
   mkdir -p po
   mkdir -p include

# Unlike Debian, Gentoo Linux does not automatically install a range of
# versions of the autotools, so a non-existent version of aclocal gets
# called when these values are defined.  I don't think these are necessary
# anymore, even on Debian.
#
# export WANT_AUTOCONF_2_5="1"
# export WANT_AUTOMAKE="1.6"

   #************************************************************************
   # Call a number of "auto" programs in the strict order shown below.  See
   # "info autopoint" for details.  Note:  Earlier versions of auto-tools
   # don't ignore duplicate definitions of macros.  (The system normally
   # provides m4 macros in /usr/share/aclocal, but the project also
   # provides them in the project's m4 directory.)
   #------------------------------------------------------------------------

   if [ ${OLDCONF} != "yes" ] ; then

      cmd ${AUTOPOINT} -f
      cmd ${ACLOCAL} -I ${M4DIR} --install
      cmd ${AUTOCONF}
      cmd ${AUTOHEADER}

   #  The LT_INIT macro of libtool 2.0 (formerly called AC_PROG_LIBTOOL)
   #  would do this, but Debian ships with version 1.5 libtool, so we have
   #  to do things the old-fashioned way.

      cmd ${LIBTOOLIZE} --automake --force --copy

   else

      cmd ${ACLOCAL} -I ${M4DIR} --install
      cmd ${AUTOCONF} -A ${M4DIR}
      cmd ${AUTOHEADER} -A ${M4DIR}

   fi

   cmd ${AUTOMAKE} --foreign --add-missing --copy

   # Automake seems to need this one, but doesn't provide it!

   cp contrib/bin/mkinstalldirs-1.10 aux-files/mkinstalldirs

   # At this point, remove files which always need to be regenerated.
   # Right now, this is done with the --clean option.

   # Tell the user about gettext, pkg-config and sed.

   case "${GETTEXT}" in

     yes) ;;
     no) cat << E_O_F

=============================================================================
NOTE: gettext is not installed on your system. The XPC build will work,
      but without internationalization support.
E_O_F
     ;;

     old) cat << E_O_F

=============================================================================
NOTE: An old version of gettext is installed on your system. The XPC
      build will work, but if libintl is not installed, there will be no
      internationalization support.  Upgrade to gettext 0.11.5 or later.
E_O_F
     ;;

   esac

   case "$PKGCONFIG" in

     yes) ;;
     no) cat << E_O_F

=============================================================================
NOTE: The "pkg-config" utility is not installed on your system; detection of
      the gtk-2.0 and GNOME 2.0 libraries will not be reliable.
E_O_F
     ;;

   esac

   case "$AUTOMAKE_BAD" in
     no) ;;
     yes) cat << E_O_F

=============================================================================
NOTE: Your version of automake has a bug which prevents proper plugin
      compilation. Either compile XPC with the --disable-plugins flag, or
      use a version of automake newer than 1.6.1 (1.6.2 is OK, and so are
      the 1.5 series).
E_O_F
     ;;

   esac

   case "$INSTALL_BAD" in

     no) ;;
     yes) cat << E_O_F

=============================================================================
NOTE: Your version of automake has a bug which prevents proper installation.
      Do not use "make install" with this version of automake, or use a
      version of automake newer than 1.5 (such as 1.6 or 1.7).
E_O_F
     ;;

   esac
 
   if [ -x /usr/bin/dot ] ; then
      echo "graphviz package found"
   else
      echo "! To build the documentation, you need to install graphviz."
   fi

   if [ -x /usr/bin/doxygen ] ; then
      echo "doxygen package found"
   else
      echo "! To build the documentation, you need to install doxygen."
   fi

   #************************************************************************
   # --intl-boot
   #------------------------------------------------------------------------

   if [ $DOINTLBOOT == "yes" ] ; then

      ./bootstrap-po --boot

   fi

   #************************************************************************
   # --configure
   #------------------------------------------------------------------------

   if [ $DOCONFIGURE == "yes" ] ; then

      DEBUGFLAG=""
      BUILDFLAG=""

      if [ $DODEBUG == "yes" ] ; then
         DEBUGFLAG="--enable-debug --disable-shared"
      fi

      echo "Running the new configure script in preparation for building."
      echo "Command:  ./configure $DEBUGFLAG $BUILDFLAG"

      if [ $DOLOG == "yes" ] ; then
         echo "$ ./configure $DEBUGFLAG $BUILDFLAG" >> $LOGFILENAME
      fi

      ./configure $DEBUGFLAG $BUILDFLAG

   else

      if [ "$DOBOOTSTRAP" == "yes" ] ; then
         echo
         echo "Now run './configure' to configure XPC for compilation, or"
         echo "'./configure --help' for configuration options.  Another good"
         echo "option is the 'build' script.  Run './build --help' for more"
         echo "information."
      fi
   fi
fi

if [ ! -f po/es.po ] && [ $DOCLEAN == "no" ] && [ $DODEBCLEAN == "no" ] ; then

      cat << E_O_F

Warning: The XPC suite has not yet had internationalization set up.  You
         have either not yet run the bootstrap-po script, or you previously
         ran the bootstrap-po script with the scary --intl-clean option.
         Internationalization needs to be set up using the --intl-boot
         option.  Run the './bootstrap-po --help' command for more information.

E_O_F

fi

#******************************************************************************
# Safety backup of configure.ac and Makefile.am
#------------------------------------------------------------------------------
#
#     Because the bootstrap-po --boot process copies files from contrib/po,
#     we want to make sure that we back up the original versions to avoid
#     accidentally losing changes.  Note the this back is currently
#     coincident with the --clean operation, which is what we usually do
#     when testing configure changes.
#
#------------------------------------------------------------------------------

if [ $DOBACKUP == "yes" ] ; then

   cp configure.ac contrib/po/configure.ac.fresh
   cp configure.ac contrib/automake/
   cp Makefile.am contrib/po/Makefile.am.fresh
   cp Makefile.am contrib/automake/

fi

#******************************************************************************
# bootstrap (XPC)
#------------------------------------------------------------------------------
# Local Variables:
# End:
#------------------------------------------------------------------------------
# vim: ts=3 sw=3 et ft=sh
#------------------------------------------------------------------------------
